{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 千帆 OpenAI 适配器\n",
    "\n",
    "对于已经适配 OpenAI 而尚未支持千帆 SDK 的用户，本文提供了一种方法，支持用户0成本从OpenAI迁移到百度文心千帆大模型平台。\n",
    "整体流程包含：\n",
    "1. 在本地使用 qianfan 启动千帆OpenAI适配器\n",
    "2. 编写 OpenAI规范 接口代码，通过调用本地千帆OpenAI适配器，请求千帆大模型平台。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install 'qianfan[openai]' -U"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 启动千帆 OpenAI 适配器"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以通过配置模型映射，将模型名称从 OpenAI 的模型映射至千帆模型:\n",
    "```yaml\n",
    "gpt-4.*: ERNIE-4.0-8K\n",
    "```\n",
    "具体示例可参考[openai_conf.yaml](./assets/openai_conf.yaml)："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "OpenAI wrapper server is running at                                             \n",
      "\n",
      "\u001b[1;33m • \u001b[0mhttp://127.0.0.1:8001                                                        \n",
      "\u001b[1;33m • \u001b[0mhttp://172.18.167.145:8001                                                   \n",
      "\n",
      "Remember to set the environment variables:                                      \n",
      "\n",
      "\u001b[40m                                                                                \u001b[0m\n",
      "\u001b[40m \u001b[0m\u001b[97;40m    \u001b[0m\u001b[97;40mexport\u001b[0m\u001b[97;40m \u001b[0m\u001b[97;40mOPENAI_API_KEY\u001b[0m\u001b[91;40m=\u001b[0m\u001b[93;40m'any-content-you-want'\u001b[0m\u001b[40m                              \u001b[0m\u001b[40m \u001b[0m\n",
      "\u001b[40m \u001b[0m\u001b[97;40m    \u001b[0m\u001b[97;40mexport\u001b[0m\u001b[97;40m \u001b[0m\u001b[97;40mOPENAI_BASE_URL\u001b[0m\u001b[91;40m=\u001b[0m\u001b[93;40m'http://172.18.167.145:8001/v1'\u001b[0m\u001b[40m                    \u001b[0m\u001b[40m \u001b[0m\n",
      "\u001b[40m                                                                                \u001b[0m\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Started server process [66674]\n",
      "INFO:     Waiting for application startup.\n",
      "INFO:     Application startup complete.\n",
      "INFO:     Uvicorn running on http://0.0.0.0:8001 (Press CTRL+C to quit)\n"
     ]
    }
   ],
   "source": [
    "# import nest_asyncio\n",
    "import os\n",
    "import subprocess as sp\n",
    "\n",
    "os.environ[\"OPENAI_API_KEY\"] = \"FAKE_KEY\"\n",
    "os.environ[\"OPENAI_BASE_URL\"] = \"http://127.0.0.1:8001/v1\"  # 修改为本地 OpenAI 适配器地址\n",
    "\n",
    "# 以下环境变量供千帆 OpenAI Adapter：\n",
    "# 使用安全认证的access_key/secret_key:\n",
    "os.environ[\"QIANFAN_ACCESS_KEY\"] = \"your_access_key\"\n",
    "os.environ[\"QIANFAN_SECRET_KEY\"] = \"your_secret_key\"\n",
    "# 或者应用ak/sk\n",
    "# os.environ[\"QIANFAN_AK\"]=\"your_app_ak\"\n",
    "# os.environ[\"QIANFAN_SK\"]=\"your_app_sk\"\n",
    "\n",
    "# 启动千帆 SDK 的 OpenAI Adapter 服务，用于代理转发指向 OpenAI 的请求，并替换为千帆服务的返回\n",
    "server = sp.Popen(\"qianfan openai -p 8001 --config-file ./assets/openai_conf.yaml --no-ignore-system\", shell=True)\n",
    "# 也可以在终端直接执行qianfan openai -p 8001 --config-file assets/openai_conf.yaml --no-ignore-system"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 调用ERNIE文心大模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INFO:     127.0.0.1:63556 - \"POST /v1/chat/completions HTTP/1.1\" 200 OK\n",
      "ChatCompletionMessage(content='炒西红柿鸡蛋的第一步就是准备好食材，包括：西红柿、鸡蛋、盐、油、葱花等。接着，打散鸡蛋，并加入少许盐搅拌均匀。然后，西红柿切块备用。在热锅中加油，油热后倒入鸡蛋液，翻炒至刚刚凝固就盛出备用。再次加油，放入葱花爆香，然后放入西红柿翻炒，炒到西红柿出汁后，放入炒好的鸡蛋，再加盐调味，翻炒均匀后即可出锅。这样就可以得到一盘即好看又好吃的西红柿炒鸡蛋了。', role='assistant', function_call=None, tool_calls=None)\n"
     ]
    }
   ],
   "source": [
    "from openai import OpenAI\n",
    "\n",
    "client = OpenAI()\n",
    "\n",
    "completion = client.chat.completions.create(\n",
    "    model=\"gpt-4\", # model=\"ERNIE-4.0-8K\",\n",
    "    messages=[{'role': 'system', 'content': 'You are a helpful assistant.'},\n",
    "              {'role': 'user', 'content': '如何做炒西红柿鸡蛋？'}]\n",
    ")\n",
    "print(completion.choices[0].message)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 千帆平台常用模型清单\n",
    "ERNIE-3.5-8K<br>\n",
    "ERNIE-4.0-8K<br>\n",
    "ERNIE-Speed-8K<br>\n",
    "ERNIE-Lite-8K<br>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 查看完整模型清单"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'AquilaChat-7B',\n",
       " 'BLOOMZ-7B',\n",
       " 'ChatGLM2-6B-32K',\n",
       " 'ChatLaw',\n",
       " 'EB-turbo-AppBuilder',\n",
       " 'ERNIE 3.5',\n",
       " 'ERNIE Speed',\n",
       " 'ERNIE Speed-AppBuilder',\n",
       " 'ERNIE-3.5-128K',\n",
       " 'ERNIE-3.5-128K（预览版）',\n",
       " 'ERNIE-3.5-8K',\n",
       " 'ERNIE-3.5-8K-0205',\n",
       " 'ERNIE-3.5-8K-0329',\n",
       " 'ERNIE-3.5-8K-0613',\n",
       " 'ERNIE-3.5-8K-Preview',\n",
       " 'ERNIE-3.5-8K-preview',\n",
       " 'ERNIE-3.5-preview',\n",
       " 'ERNIE-4.0-8K',\n",
       " 'ERNIE-4.0-8K-0104',\n",
       " 'ERNIE-4.0-8K-0329',\n",
       " 'ERNIE-4.0-8K-0613',\n",
       " 'ERNIE-4.0-8K-Latest',\n",
       " 'ERNIE-4.0-8K-Preview',\n",
       " 'ERNIE-4.0-8K-Preview-0518',\n",
       " 'ERNIE-4.0-8K-preview',\n",
       " 'ERNIE-4.0-preview',\n",
       " 'ERNIE-Bot',\n",
       " 'ERNIE-Bot-4',\n",
       " 'ERNIE-Bot-turbo',\n",
       " 'ERNIE-Bot-turbo-AI',\n",
       " 'ERNIE-Character-8K',\n",
       " 'ERNIE-Character-Fiction-8K',\n",
       " 'ERNIE-Function-8K',\n",
       " 'ERNIE-Functions-8K',\n",
       " 'ERNIE-Lite-8K',\n",
       " 'ERNIE-Lite-8K-0308',\n",
       " 'ERNIE-Lite-8K-0922',\n",
       " 'ERNIE-Lite-8K-0922（原ERNIE-Bot-turbo-0922）',\n",
       " 'ERNIE-Speed',\n",
       " 'ERNIE-Speed-128K',\n",
       " 'ERNIE-Speed-8K',\n",
       " 'ERNIE-Tiny-8K',\n",
       " 'Gemma-7B-It',\n",
       " 'Gemma-7B-it',\n",
       " 'Llama-2-13B-Chat',\n",
       " 'Llama-2-70B-Chat',\n",
       " 'Llama-2-7B-Chat',\n",
       " 'Meta-Llama-3-70B',\n",
       " 'Meta-Llama-3-8B',\n",
       " 'Mixtral-8x7B-Instruct',\n",
       " 'Qianfan-BLOOMZ-7B-compressed',\n",
       " 'Qianfan-Chinese-Llama-2-13B',\n",
       " 'Qianfan-Chinese-Llama-2-70B',\n",
       " 'Qianfan-Chinese-Llama-2-7B',\n",
       " 'XuanYuan-70B-Chat-4bit',\n",
       " 'Yi-34B-Chat'}"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from qianfan import ChatCompletion\n",
    "ChatCompletion().models()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "py11",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  },
  "vscode": {
   "interpreter": {
    "hash": "42453736f0d03c53e6ad75478ebb5fcf2abe6d38094996bfa938cecc75099885"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
